package com.hyt.it.ogt.kq.service.gov.den;

import com.hyt.it.ogt.kq.common.config.ConfigManager;
import com.hyt.it.ogt.kq.common.gov.constant.CodeEnum;
import com.hyt.it.ogt.kq.common.config.exception.KqException;
import com.hyt.it.ogt.kq.common.gov.utils.Constants;
import com.hyt.it.ogt.kq.common.gov.utils.FileUtil;
import com.hyt.it.ogt.kq.service.gov.mapper.TimeRoomCandidateMapper;
import com.hyt.it.ogt.kq.service.gov.model.entity.ObtRoomData;
import com.hyt.it.ogt.kq.service.gov.roomdata.model.obt.ObtCandidate;
import com.hyt.it.ogt.kq.service.gov.service.ITaskService;
import com.hyt.it.ogt.kq.service.gov.service.ITimeRoomCandidateService;
import com.hyt.it.ogt.kq.service.gov.service.ITimeRoomService;
import com.hyt.it.ogt.kq.service.gov.service.obs.CloudObsService;
import com.linuxense.javadbf.DBFDataType;
import com.linuxense.javadbf.DBFField;
import com.linuxense.javadbf.DBFWriter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;

/**
 * 编排结果导出
 *
 * @author huangyh
 * @since 2021/11/6 20:22
 */
@Slf4j
@Component
public class ArrangedResultExportUtil {

    @Resource
    private TimeRoomCandidateMapper timeRoomCandidateMapper;
    @Resource
    private ITimeRoomService iTimeRoomService;
    @Resource
    private ITimeRoomCandidateService iTimeRoomCandidateService;
    @Resource
    private ITaskService iTaskService;
    @Resource
    private ConfigManager configManager;
    @Resource
    private CloudObsService cloudObsService;


    public Future<File> creatKdDbf(String taskId, File root) {
        //获取考生dbf数据
        List<Map<String, Object>> dataList = timeRoomCandidateMapper.getKdDbf(taskId);
        //创建临时文件
        File dbf = new File(root, "kd.dbf");
        log.info("# 考生dbf临时文件所在本地路径: {}", dbf.getAbsolutePath());
        //创建dbf表字段
        DBFField[] fields = this.getKdDBFField();
        this.creatDbf(dbf, dataList, fields);
        return new AsyncResult<>(dbf);
    }

    private DBFField[] getKdDBFField() {
        DBFField[] fields = new DBFField[9];
        //1.准考证号
        fields[0] = new DBFField();
        fields[0].setName("kddm");
        fields[0].setType(DBFDataType.CHARACTER);
        fields[0].setLength(20);
        //2.性别
        fields[1] = new DBFField();
        fields[1].setName("kdxh");
        fields[1].setType(DBFDataType.CHARACTER);
        fields[1].setLength(12);
        //3.姓名
        fields[2] = new DBFField();
        fields[2].setName("kdmc");
        fields[2].setType(DBFDataType.CHARACTER);
        fields[2].setLength(100);
        //4.证件类型
        fields[3] = new DBFField();
        fields[3].setName("kddz");
        fields[3].setType(DBFDataType.CHARACTER);
        fields[3].setLength(100);
        //5.证件号
        fields[4] = new DBFField();
        fields[4].setName("kqcode");
        fields[4].setType(DBFDataType.CHARACTER);
        fields[4].setLength(20);
        //6.座位号
        fields[5] = new DBFField();
        fields[5].setName("kcrs");
        fields[5].setType(DBFDataType.CHARACTER);
        fields[5].setLength(12);
        //7.考场编号
        fields[6] = new DBFField();
        fields[6].setName("kcxh");
        fields[6].setType(DBFDataType.CHARACTER);
        fields[6].setLength(12);
        //8.市编码
        fields[7] = new DBFField();
        fields[7].setName("kcmc");
        fields[7].setType(DBFDataType.CHARACTER);
        fields[7].setLength(100);
        //9.考点编号
        fields[8] = new DBFField();
        fields[8].setName("kspc");
        fields[8].setType(DBFDataType.CHARACTER);
        fields[8].setLength(12);
        return fields;
    }

    public Future<File> creatKpDbf(String taskId, File root) {
        //获取考生dbf数据
        List<Map<String, Object>> dataList = timeRoomCandidateMapper.getKpDbf(taskId);
        //创建临时文件
        File dbf = new File(root, "kp.dbf");
        log.info("# 考生dbf临时文件所在本地路径: {}", dbf.getAbsolutePath());
        //创建dbf表字段
        DBFField[] fields = this.getKpDBFField();
        this.creatDbf(dbf, dataList, fields);
        return new AsyncResult<>(dbf);
    }

    private DBFField[] getKpDBFField() {
        DBFField[] fields = new DBFField[2];
        //1.准考证号
        fields[0] = new DBFField();
        fields[0].setName("code");
        fields[0].setType(DBFDataType.CHARACTER);
        fields[0].setLength(20);
        //2.性别
        fields[1] = new DBFField();
        fields[1].setName("name");
        fields[1].setType(DBFDataType.CHARACTER);
        fields[1].setLength(100);
        return fields;
    }

    public Future<File> creatKqDbf(String taskId, File root) {
        //获取考生dbf数据
        List<Map<String, Object>> dataList = timeRoomCandidateMapper.getKqDbf(taskId);
        //创建临时文件
        File dbf = new File(root, "kq.dbf");
        log.info("# 考生dbf临时文件所在本地路径: {}", dbf.getAbsolutePath());
        //创建dbf表字段
        DBFField[] fields = this.getKqDBFField();
        this.creatDbf(dbf, dataList, fields);
        return new AsyncResult<>(dbf);
    }

    private DBFField[] getKqDBFField() {
        DBFField[] fields = new DBFField[2];
        //1.准考证号
        fields[0] = new DBFField();
        fields[0].setName("kqdm");
        fields[0].setType(DBFDataType.CHARACTER);
        fields[0].setLength(20);
        //2.性别
        fields[1] = new DBFField();
        fields[1].setName("kqmc");
        fields[1].setType(DBFDataType.CHARACTER);
        fields[1].setLength(100);
        return fields;
    }

    public Future<File> creatKsDbf(String taskId, File root) {
        //获取考生dbf数据
        List<Map<String, Object>> dataList = timeRoomCandidateMapper.getCandidateDbf(taskId);
        //创建临时文件
        File dbf = new File(root, "ks.dbf");
        log.info("# 考生dbf临时文件所在本地路径: {}", dbf.getAbsolutePath());
        //创建dbf表字段
        DBFField[] fields = this.getKsDBFField();
        this.creatDbf(dbf, dataList, fields);
        return new AsyncResult<>(dbf);
    }

    public Future<File> creatDbf(File dbf, List<Map<String, Object>> dataList, DBFField[] fields) {
        try {
            //创建DBFWriter
            DBFWriter writer = new DBFWriter(dbf, Charset.forName("GBK"));
            //设置字段
            writer.setFields(fields);
            for (Map<String, Object> map : dataList) {
                Object[] data = new Object[fields.length];
                for (int i = 0; i < fields.length; i++) {
                    DBFField dbfEntity = fields[i];
                    data[i] = map.get(dbfEntity.getName().toLowerCase()).toString();
                }
                writer.addRecord(data);
            }
            //关闭DBFWriter
            writer.close();
            return new AsyncResult<>(dbf);
        } catch (Exception e) {
            if (dbf != null) {
                if (!dbf.delete()) {
                    log.error("删除dbf临时文件失败，临时文件所在本地路径:{}", dbf.getAbsolutePath(), e);
                }
            }
            throw new KqException(11111, "生成dbf文件失败");
        }
    }

    private DBFField[] getKsDBFField() {
        DBFField[] fields = new DBFField[17];
        //1.准考证号
        fields[0] = new DBFField();
        fields[0].setName("Zkzh");
        fields[0].setType(DBFDataType.CHARACTER);
        fields[0].setLength(30);
        //2.性别
        fields[1] = new DBFField();
        fields[1].setName("Sex");
        fields[1].setType(DBFDataType.CHARACTER);
        fields[1].setLength(12);
        //3.姓名
        fields[2] = new DBFField();
        fields[2].setName("Name");
        fields[2].setType(DBFDataType.CHARACTER);
        fields[2].setLength(50);
        //4.证件类型
        fields[3] = new DBFField();
        fields[3].setName("Zjlx");
        fields[3].setType(DBFDataType.CHARACTER);
        fields[3].setLength(12);
        //5.证件号
        fields[4] = new DBFField();
        fields[4].setName("Sfzh");
        fields[4].setType(DBFDataType.CHARACTER);
        fields[4].setLength(20);
        //6.座位号
        fields[5] = new DBFField();
        fields[5].setName("Seatno");
        fields[5].setType(DBFDataType.CHARACTER);
        fields[5].setLength(12);
        //7.考场编号
        fields[6] = new DBFField();
        fields[6].setName("Classno");
        fields[6].setType(DBFDataType.CHARACTER);
        fields[6].setLength(12);
        //8.市编码
        fields[7] = new DBFField();
        fields[7].setName("Kqdm");
        fields[7].setType(DBFDataType.CHARACTER);
        fields[7].setLength(20);
        //9.考点编号
        fields[8] = new DBFField();
        fields[8].setName("Kddm");
        fields[8].setType(DBFDataType.CHARACTER);
        fields[8].setLength(20);
        //10.场次编号
        fields[9] = new DBFField();
        fields[9].setName("Ccdm");
        fields[9].setType(DBFDataType.CHARACTER);
        fields[9].setLength(12);
        //11.拓展字段1
        fields[10] = new DBFField();
        fields[10].setName("Tzmlx1");
        fields[10].setType(DBFDataType.CHARACTER);
        fields[10].setLength(20);
        //12.拓展字段2
        fields[11] = new DBFField();
        fields[11].setName("Tzm1");
        fields[11].setType(DBFDataType.CHARACTER);
        fields[11].setLength(20);
        //13.拓展字段3
        fields[12] = new DBFField();
        fields[12].setName("Tzmlx2");
        fields[12].setType(DBFDataType.CHARACTER);
        fields[12].setLength(20);
        //14.拓展字段4
        fields[13] = new DBFField();
        fields[13].setName("Tzm2");
        fields[13].setType(DBFDataType.CHARACTER);
        fields[13].setLength(20);
        //15.科目编号
        fields[14] = new DBFField();
        fields[14].setName("Kmdm");
        fields[14].setType(DBFDataType.CHARACTER);
        fields[14].setLength(20);
        //16.作答方式
        fields[15] = new DBFField();
        fields[15].setName("Zdfs");
        fields[15].setType(DBFDataType.CHARACTER);
        fields[15].setLength(12);
        //17.拓展字段5
        fields[16] = new DBFField();
        fields[16].setName("Lxfs");
        fields[16].setType(DBFDataType.CHARACTER);
        fields[16].setLength(20);
        return fields;
    }



    public void creatCandidatePhoto(String taskId, File root) {

        List<ObtRoomData> rooDataList = iTimeRoomService.getObtRoomDataList(taskId);
        Integer type = iTaskService.taskDataType(taskId);

        for (int i = 0; i < rooDataList.size(); i++) {
            ObtRoomData obtRoomData = rooDataList.get(i);
            List<ObtCandidate> candidates = iTimeRoomCandidateService.getCandidateList(taskId, obtRoomData.getTimeRoomId());

            for (ObtCandidate item : candidates) {
                if (StringUtils.isNotBlank(item.getPhoto())) {
                    String photoUrl = item.getPhoto();
                    InputStream inputStream = null;
                    try {
                        if (type.equals(CodeEnum.TASK_DATA_TYPE_BM.getCode())) {
                            String fileName = StringUtils.join(configManager.getBmPicPath(),photoUrl);
                            log.info("下载考生照片(文件服务器)，{}，{}",type,fileName);
                            inputStream = FileUtil.getPhotoUrl(fileName) ;
                        } else {
                            log.info("下载考生照片(华为云)，{}，{}",type,photoUrl);
                            inputStream = cloudObsService.downFile(photoUrl);
                        }

                        String fileNamePath = item.getStudentId() + Constants.JPG;
                        FileUtil.writeFile(inputStream, root + File.separator + "photo" + File.separator + fileNamePath);
                        item.setPhoto(fileNamePath);
                    } catch (Exception e) {
                        log.error("生成考务包时下载考生照片异常（忽略异常）：{}", e.getMessage());
                        item.setPhoto("");
                    } finally {
                        try {
                            if (inputStream != null) {
                                inputStream.close();
                            }
                        } catch (IOException e) {

                        }
                    }
                } else {
                    item.setPhoto("");
                }
            }

        }
    }

    public DBFField[] getBmkDBFField() {
        DBFField[] fields = new DBFField[23];
        //1.准考证号
        fields[0] = new DBFField();
        fields[0].setName("Zkzh");
        fields[0].setType(DBFDataType.CHARACTER);
        fields[0].setLength(30);
        //2.姓名
        fields[1] = new DBFField();
        fields[1].setName("Xm");
        fields[1].setType(DBFDataType.CHARACTER);
        fields[1].setLength(100);
        //3.性别
        fields[2] = new DBFField();
        fields[2].setName("Xb");
        fields[2].setType(DBFDataType.CHARACTER);
        fields[2].setLength(4);
        //4.考场编号
        fields[3] = new DBFField();
        fields[3].setName("Kcdm");
        fields[3].setType(DBFDataType.CHARACTER);
        fields[3].setLength(20);
        //5.考场名称
        fields[4] = new DBFField();
        fields[4].setName("Kcmc");
        fields[4].setType(DBFDataType.CHARACTER);
        fields[4].setLength(254);
        //6.考点编号
        fields[5] = new DBFField();
        fields[5].setName("Kddm");
        fields[5].setType(DBFDataType.CHARACTER);
        fields[5].setLength(10);
        //7.考点名称
        fields[6] = new DBFField();
        fields[6].setName("Kdmc");
        fields[6].setType(DBFDataType.CHARACTER);
        fields[6].setLength(254);
        //8.省份编码
        fields[7] = new DBFField();
        fields[7].setName("Sfdm");
        fields[7].setType(DBFDataType.CHARACTER);
        fields[7].setLength(10);
        //9.省份名称
        fields[8] = new DBFField();
        fields[8].setName("Sfmc");
        fields[8].setType(DBFDataType.CHARACTER);
        fields[8].setLength(20);
        //10.市编号
        fields[9] = new DBFField();
        fields[9].setName("Sdm");
        fields[9].setType(DBFDataType.CHARACTER);
        fields[9].setLength(10);
        //11.市名称
        fields[10] = new DBFField();
        fields[10].setName("Smc");
        fields[10].setType(DBFDataType.CHARACTER);
        fields[10].setLength(20);
        //12.县区编号
        fields[11] = new DBFField();
        fields[11].setName("Xqdm");
        fields[11].setType(DBFDataType.CHARACTER);
        fields[11].setLength(10);
        //13.县区名称
        fields[12] = new DBFField();
        fields[12].setName("Xqmc");
        fields[12].setType(DBFDataType.CHARACTER);
        fields[12].setLength(20);
        //14.科目编号
        fields[13] = new DBFField();
        fields[13].setName("Kmdm");
        fields[13].setType(DBFDataType.CHARACTER);
        fields[13].setLength(10);
        //15.科目名称
        fields[14] = new DBFField();
        fields[14].setName("Kmmc");
        fields[14].setType(DBFDataType.CHARACTER);
        fields[14].setLength(40);
        //16.批次编号
        fields[15] = new DBFField();
        fields[15].setName("Pcdm");
        fields[15].setType(DBFDataType.CHARACTER);
        fields[15].setLength(10);
        //17.批次名称
        fields[16] = new DBFField();
        fields[16].setName("Pcmc");
        fields[16].setType(DBFDataType.CHARACTER);
        fields[16].setLength(20);
        //18.座位号
        fields[17] = new DBFField();
        fields[17].setName("Zwh");
        fields[17].setType(DBFDataType.CHARACTER);
        fields[17].setLength(10);
        //19.语种
        fields[18] = new DBFField();
        fields[18].setName("Yz");
        fields[18].setType(DBFDataType.CHARACTER);
        fields[18].setLength(10);
        //20.是否特殊人群
        fields[19] = new DBFField();
        fields[19].setName("Trsq");
        fields[19].setType(DBFDataType.CHARACTER);
        fields[19].setLength(10);
        //21.身份证号码
        fields[20] = new DBFField();
        fields[20].setName("Sfzh");
        fields[20].setType(DBFDataType.CHARACTER);
        fields[20].setLength(18);

        fields[21] = new DBFField();
        fields[21].setName("Sdkch");
        fields[21].setType(DBFDataType.CHARACTER);
        fields[21].setLength(10);
        //23.作答方式
        fields[22] = new DBFField();
        fields[22].setName("Zdfs");
        fields[22].setType(DBFDataType.CHARACTER);
        fields[22].setLength(10);
        return fields;
    }

    public DBFField[] getPcDBFField(){
        DBFField[] fields = new DBFField[8];
        //1.考试编号
        fields[0] = new DBFField();
        fields[0].setName("EXAMID");
        fields[0].setType(DBFDataType.CHARACTER);
        fields[0].setLength(20);
        //2.批次编号
        fields[1] = new DBFField();
        fields[1].setName("TIMEID");
        fields[1].setType(DBFDataType.CHARACTER);
        fields[1].setLength(20);
        //3.批次名称
        fields[2] = new DBFField();
        fields[2].setName("TIMENAME");
        fields[2].setType(DBFDataType.CHARACTER);
        fields[2].setLength(30);
        //4.开始时间
        fields[3] = new DBFField();
        fields[3].setName("STARTTIME");
        fields[3].setType(DBFDataType.CHARACTER);
        fields[3].setLength(20);
        //5.结束时间
        fields[4] = new DBFField();
        fields[4].setName("ENDTIME");
        fields[4].setType(DBFDataType.CHARACTER);
        fields[4].setLength(20);
        //6.考试时长
        fields[5] = new DBFField();
        fields[5].setName("TIMELENHTH");
        fields[5].setType(DBFDataType.CHARACTER);
        fields[5].setLength(4);
        //7.是否当前批次
        fields[6] = new DBFField();
        fields[6].setName("ISCURRENT");
        fields[6].setType(DBFDataType.CHARACTER);
        fields[6].setLength(4);
        //8.类型
        fields[7] = new DBFField();
        fields[7].setName("TYPE");
        fields[7].setType(DBFDataType.CHARACTER);
        fields[7].setLength(4);

        return fields;
    }

}
